How do I properly subclass with glib using Rust? - rust

Im following this tutorial, because I want to create a gstreamer plugin. I think the tutorial I a bit outdated, but the Cargo.toml files don't specify which versions they're using for the tutorial. I'm having some problems with glib, and I was hoping someone with more experience with glib could help me.
The tutorial prompts me to write the following lines.
I added the errors I'm getting, and the things I've already tried in the comments:
mod rgb2gray/imp
#[derive(Default)]
pub struct Rgb2Gray {}
impl Rgb2Gray {}
// This macro doesn't seem to exist
// I tried putting "glib::glib_object_subclass!();" inside the struct (???)
// after that I get: "the trait `glib::subclass::object::ObjectImpl` is not implemented for `rgb2gray::imp::Rgb2Gray`"
#[glib::object_subclass]
impl ObjectSubclass for Rgb2Gray {
const NAME: &'static str = "RsRgb2Gray";
type Type = super::Rgb2Gray; // TYPE is not a variable in ObjectSubclass
type ParentType = gst_base::BaseTransform;
}
mod rgb2gray
mod imp;
// Again, this macro doesn't seem to exist
// I tried glib::glib_wrapper
glib::wrapper! {
// The following line doesn't accept ObjectSubclass, it does accept Boxed, or Object, or Shared.
// I tried Object, but then it wants more information in the angle brackets... And I'm not sure what kind of information.
pub struct Rgb2Gray(ObjectSubclass<imp::Rgb2Gray>) #extends gst_base::BaseTransform, gst::Element, gst::Object;
}
// more code...

Did you compare it to the code at https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/tree/master/tutorial ? That one builds fine, so I assume that somewhere the code and the markdown are not in sync.
Judging from the error you wrote on above, you are using the latest release of glib and not the git version. See the Cargo.toml in there for how to select the git version.
If you're using the latest release you need the code/markdown from the 0.6 branch here: https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/tree/0.6/tutorial

Related

How to use #[deprecated] for renaming public struct in backwards compatible way?

I see that I can use the #[deprecated] marker, but somehow it is not working in the following workflow:
I renamed all my MyOldStruct to MyNewStruct in my library.
Added a #deprecated note to pub use MyNewStruct as MyOldStruct.
pub struct MyNewStruct{};
#[deprecated]
pub use MyOldStruct as MyNewStruct;
Any ideas what might be going wrong here? I am viewing if it shows as deprecated in cargo docs.
Use a type alias:
#[deprecated]
pub type MyOldStruct = MyNewStruct;
See it emit a warning on the playground.
I will note that using a type alias for renaming and deprecating things doesn't work for everything: an aliased tuple struct can't use the new name construct a value as shown in the docs, and this method obviously doesn't work for traits since they aren't types and we don't have trait aliases yet.

How can I add rustdoc comments to proc macro-generated code?

I wrote a proc-macro library to accompany a library I'm writing - they go together, with the former being used to abstract away a lot of redundant code in the latter.
I am successfully generating several structs and impls in my proc macro. I am also using cargo doc with the library, and my documentation is what I expect. However, the documentation comments I'm creating in my proc macro aren't working as expected. Some code from my proc macro looks roughly like this:
#[proc_macro_derive(MyDerive)]
pub fn derive(input: TokenStream) -> TokenStream {
...
let expanded = quote! {
...
impl #my_struct {
/// This comment doesn't show up in documentation
pub fn foo(&self, n: i32) -> bool {
false
}
/// This comment DOES show up in documentation
pub fn bar(n: i32) -> Vec<String> {
...
}
}
}
expanded.into()
}
When I open up the generated documentation:
foo itself shows up in the documentation, but its comment doesn't
bar and its comment are in the documentation
If I change the comment for bar, the comment is not updated.
This third point tells me that I probably used some cargo doc flag at some point that works correctly, but I'm now using a different set of flags that don't work with proc macros. I don't want to document all my external crate dependencies (--no-deps), but I do want to document my private items (--document-private-items). I'm therefore generating docs with cargo doc --no-deps --document-private-items. I've also tried with --release.
I assume documentation is built from the source code and not from the built .so file itself, so I haven't been doing cargo build before doing cargo doc, though I have also tried this to debug this issue. So what is the right way to make sure my proc macro-generated code's documentation gets properly generated and updated?

The code reference in `crates.io` does not match with the actual crate

I'm very new to rust's syntax of using libraries. Well, mostly new to rust overall.
I've included a library, that is unfinished, and seemingly doesn't work. The library is called "hours", the lib.rs contains the following:
// #[derive(Clone, Debug, PartialEq, Eq)]
pub struct Hours {
pub rules: Vec<types::RuleSequence>,
pub tz: Tz,
}
impl Hours {
pub fn from(s: &str, tz: Tz) -> Result<Self, String> {
//... abbreviated
}
pub fn at(self: &Self, dt: &DateTime<Tz>) -> types::Modifier {
//... abbreviated
}
}
It is included in Cargo.toml: relevant lines:
edition = "2018"
[dependencies]
hours = "0.0.1"
I want to know if it is possible to include and use the from() function, so far, I'm without luck. Here's what I tried:
use hours;
fn main() {
//... abbreviated
let hours = Hours::from(example_hrs, Amsterdam).unwrap();
}
Gives compile error: Hours::from(example_hrs, Amsterdam).unwrap(); ^^^^^ use of undeclared type or moduleHours``
use hours::Hours;
fn main() {
//... abbreviated
let hours = Hours::from(example_hrs, Amsterdam).unwrap();
}
Gives compile error: use hours::Hours; ^^^^^^^^^^^^ no ``Hours`` in the root
use hours;
fn main() {
//... abbreviated
let hours = hours::Hours::from(example_hrs, Amsterdam).unwrap();
}
Gives compile error: hours::Hours::from(example_hrs, Amsterdam).unwrap(); ^^^^^ could not findHoursinhours``
Is there any way to include and use this library? Do I need to change the library, or am I simply using it wrong?
Problem in here, the code in repository link you've shared doesn't match with the dependency in crates.io and naturally Rust can't find the required api components. In this case owner of the crate hasn't published the code in gitlab yet.
To see that you can quickly check the source from the docs.rs. This is the link for the required dependency docs.rs/crate/hours/0.0.1/source/.
If you want to use the current code in the repository
you may have it locally by downloading(or using git clone) then you can use it by specifying the path in cargo.toml
Or define git repository directly in cargo toml.
hours = { git = "https://gitlab.com/alantrick/hours.git", rev="7b7d369796c209db7b61db71aa7396f2ec59f942"}
Adding revision number or tag might help since the updates on master branch may break the compatibility.
Why this source in docs.rs is accurate with crates.io ?
Please check the about section in docs.rs :
Docs.rs automatically builds crates' documentation released on
crates.io using the nightly release of the Rust compiler
This means it is synchronized with crates.io.
To be sure you can also check the crate's source from a local repository cache.
## Note that this path is built with default cargo settings
$HOME/.cargo/registry/src/github.com-1ecc6299db9ec823/hours-0.0.1
^^^^^^^^^^^^^^^^^^^^^^^^^^^ github reigstry for crates io
Why crate's repository link in crates.io doesn't match with the crate's source
Please check the publishing crate reference, repository information is specified in package's metadata(in cargo.toml).
According to package metadata reference these information are used for :
These URLs point to more information about the package. These are
intended to be webviews of the relevant data, not necessarily compatible
with VCS tools and the like.
documentation = "..."
homepage = "..."
repository = "..."
You may also check the popular crates as well, they point their github(usually) main page which points master branch, not a tag of the current version.

How to properly reference the same code as a dependency of a dependency?

I've got a toy project that's using the Amethyst game engine. I'm trying to write my own System for collecting user input, similar to the FlyMovementSystem and ArcBallRotationSystem they have implemented here.
It appears the right way to go about collecting mouse movements is via an EventChannel<Event>, where Event comes from the winit crate, which Amethyst depends on, but does not re-export.
What's the "right" way to reference the same winit::Event that Amethyst does?
Should I add winit to my Cargo.toml file? If so, what is the recommended way to specify the version? (Is there some keyword I can use instead of a specific version number, to allow me to "inherit" the dependency from Amethyst?)
Is referencing sub-dependencies actually discouraged? If so, what should I be doing instead?
There is currently no great solution to this problem. The best workaround is to add a direct dependency on the same version of the transitive dependency:
[dependencies]
foo = "0.1"
bar = "0.2" # `foo` depends on bar 0.2 and we need to keep these in sync
You can use tools like cargo tree to manually identify the versions needed by foo and keep your Cargo.toml up to date. I highly recommend adding a comment specifying why you've picked a specific version.
If the crate is very difficult to use without also using the underlying dependency alongside it, I'd also encourage you to file an issue with the parent crate to request that they re-export what is needed. A good example of this is the Tokio crate, which re-exports large chunks of the futures crate.
Similar to your idea, I proposed having a way to use the same version as a dependency. Instead, the Cargo team opted to add the distinction of public and private dependencies. While this will be a better solution from an engineering point of view, very little progress has been made on the implementation of it.
See also:
Why is a trait not implemented for a type that clearly has it implemented?
I'm leaving #Shepmaster's answer as the accepted one, as it answers the general question I was going for. But thanks to a gentle push from #trentcl, in case anyone found this question specifically for its relation to Amethyst, here's what I ended up doing.
Don't try to get the winit::Events at all.
When you attach an InputBundle<AX, AC> to your GameData, it sets up an InputSystem<AX, AC>, which re-publishes winit::Events in the form of InputEvent<AC>.
It does this by setting up an EventChannel<InputEvent<AC>> as a Resource, which you can access via the Read type in the ECS system. EventChannels and their usage are explained in the Amethyst Book.
I've since switched to a different approach for handling my user input, but here's roughly what it looked like (note: Amethyst a little after v0.10.0):
pub struct MouseMovementSystem {
reader: Option<ReaderId<InputEvent<()>>>, // AC = ()
}
impl<'s> System<'s> for MouseMovementSystem {
type SystemData = (
Read<'s, EventChannel<InputEvent<()>>>,
/* and others */
}
fn run(&mut self, (events, /* and others */): Self::SystemData) {
let foo = events.read(self.reader.as_mut().unwrap())
.yadda_yadda(/* ... */); // event processing logic
do_stuff(foo);
}
fn setup(&mut self, res: &mut Resources) {
use amethyst::core::specs::prelude::SystemData;
Self::SystemData::setup(res);
self.reader = Some(res.fetch_mut::<EventChannel<InputEvent<()>>>().register_reader());
}
}

How to link to other fns/structs/enums/traits in rustdoc?

I'm building a Rust library and want to give it some polish. In the rustdoc, I'd sometimes like to link to other parts of the library within the docs, e.g. fns, traits or structs. What is the official syntax for this?
As of Rust 1.48, you can now rely on RFC 1946. This adds the concept of intra-documentation links. This allows using Rust paths as the URL of a link:
[Iterator](std::iter::Iterator)
[Iterator][iter], and somewhere else in the document: [iter]: std::iter::Iterator
[Iterator], and somewhere else in the document: [Iterator]: std::iter::Iterator
The RFC also introduces "Implied Shortcut Reference Links". This allows leaving out the link reference, which is then inferred automatically.
[std::iter::Iterator], without having a link reference definition for Iterator anywhere else in the document
[`std::iter::Iterator`], without having a link reference definition for Iterator anywhere else in the document (same as previous style but with back ticks to format link as inline code)
As a concrete example, this source code:
//! Check out [ExampleStruct], especially [this
//! method](ExampleStruct::foo), but [the trait method][trait] is also
//! cool. There is also [an enum variant you can
//! use](nested::ExampleEnum::Beta).
//!
//! [trait]: ExampleTrait::bar
pub struct ExampleStruct;
impl ExampleStruct {
pub fn foo(&self) {}
}
pub trait ExampleTrait {
fn bar();
}
pub mod nested {
pub enum ExampleEnum {
Alpha,
Beta,
}
}
Produces this documentation:
Specifically, this HTML is generated:
<p>Check out ExampleStruct, especially this method, but the trait method is also cool. There is also an enum variant you can use.</p>
As of Rust 1.48, Rustdoc now supports direct intra-doc links.
Pre Rust 1.48:
Rustdoc seems to generate mostly deterministic filenames for constituent elements of a crate. Therefore if you have an enum named Complex you can generally link to it using:
[Complex](enum.Complex.html)
Similarly a struct called Point would look like:
[Point](struct.Point.html)
This should carry over to most definitions (fn, trait, and so on).
For referencing elements of a crate at different nesting levels, you can use relative paths (where each module is its own folder):
[Point](../model/struct.Point.html)
or use absolute paths:
[Point](/crate_name/model/struct.Point.html)
More of these "conventions", including anchors for specific fields, etc., can be deduced if one builds docs (cargo doc --no-deps --open) and navigates to the field or item they want and takes note of the URL. Remember that only pub items are published to docs.
If one wants to link some specific part of a struct e.g., a method named foo in the same struct (using stable rust, not nightly)
[foo](#method.foo)
or if it is in another struct
[foo](struct.OtherStruct.html#method.foo)
In Rust 1.49 nightly it works (1.48 stable not released yet):
[super::structs::WebApiResponse]
[mycrate::structs::WebApiResponse]
etc.
Read here
Since the documentation is written in Markdown, just use the Markdown syntax for Hyperlinks; i.e.
[anchor text](URL)
Also, take a look at this: https://doc.rust-lang.org/book/documentation.html

Resources