Define a static boolean in Rust from std::env::consts::OS=="windows" - rust

I'd like to create a global static boolean value called IS_WINDOWS in a Rust file:
lazy_static! {
pub static ref IS_WINDOWS: bool = std::env::consts::OS=="windows";
}
However, when I do this, anything that references the IS_WINDOWS value from elsewhere doesn't see it as a bool, they instead see it as a custom IS_WINDOWS struct, i.e. trying to do:
if crate::globals::IS_WINDOWS {
}
...results in error:
mismatched types
expected `bool`, found struct `globals::IS_WINDOWS`

Turns out, all I needed to do is use * to dereference the static variable:
if *crate::globals::IS_WINDOWS {
}

Related

How do I resolve 'expected struct, found reference` for borrowed value?

I get an error referencing a boxed value:
error[E0308]: mismatched types
--> src/interpreter.rs:284:37
|
284 | table[index].function = method;
| ^^^^^^ expected struct `Box`, found `&Box<MethodType>`
|
= note: expected struct `Box<MethodType>`
found reference `&Box<MethodType>`
If I dereference it by saying *method I get an error because MethodType doesn't implement Copy (which would be a pain, because it includes a couple of Vecs and it would be very expensive to copy). Maybe I could fix it with ManuallyDrop, but that doesn't seem very idiomatic, and I spent some time this afternoon getting rid of a ManuallyDrop.
Perhaps I shouldn't be passing it by reference (the only two calls to addMethodToTable are in the following method, addMethodToDispatch but they are in loops, because I need to try allocation several times). Maybe it should be an Rc instead.
This is part of a lot of code, so I hope this snippit is enough to show what I'm doing wrong:
#[derive(Clone)]
enum MethodType {
Function(Function),
Method(Method),
NoType,
}
#[derive(Clone)]
struct MethodMatch {
selector: usize,
function: Box<MethodType>,
}
pub struct Dispatch {
class: Object,
table: Box<[MethodMatch]>,
}
fn addMethodToTable(table:&mut Vec<MethodMatch>,selector:usize,method:&Box<MethodType>) -> bool {
let len = table.capacity();
let hash = selector%(len-DISPATCH_OVERFLOW);
for index in hash..hash+DISPATCH_OVERFLOW {
if let SelectorMatch::Other = table[index].selector_match(selector) {
// slot taken
} else {
table[index].selector = selector;
table[index].function = method;
return true
}
}
false
}
fn addMethodToDispatch(class:ClassIndex,selector:Object,method:Box<MethodType>) {
let selector = selector.raw()>>3;
while ... {
table = Vec::with_capacity(count+DISPATCH_OVERFLOW);
addMethodToTable(&mut table,selector,&method);
for mm in disp.table.iter() {
if addMethodToTable(&mut table,mm.selector,&mm.function) {unfinished = true;break}
}
}
table.resize(table.capacity(),Default::default());
disp.table=table.into_boxed_slice()
},
index => {
disp.table[index].selector = selector;
disp.table[index].function = method
},
I was having such a productive day until I hit this... thinking I was finally "getting" Rust!
Your struct expects an owned type - function must be a Box:
#[derive(Clone)]
struct MethodMatch {
selector: usize,
function: Box<MethodType>,
}
but in your other method the parameter method is a reference to a Box which are two very different types:
`fn addMethodToTable(....,method: &Box<MethodType>)
There are two ways to fix the issue (not all may be applicable in your case):
Change the reference to an owned type: method: &Box<MethodType> should become method: Box<MethodType>
Because your MethodType implements Clone, just clone it in order to get an owned type from the reference: table[index].function = method.clone();
If you are free to change the struct definition, you can use Rc<T> instead of Box<T>. Thus you can use Rc::clone(reference) and clone only the pointer instead of the whole struct.

"statics cannot evaluate destructors" in Rust

I'm getting the follow compile error:
static optionsRegex: regex::Regex
= match regex::Regex::new(r###"$(~?[\w-]+(?:=[^,]*)?(?:,~?[\w-]+(?:=[^,]*)?)*)$"###) {
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ statics cannot evaluate destructors
Ok(r) => r,
Default => panic!("Invalid optionsRegex")
};
More details: I need to access a compiled regexp to be used by struct when creating. Any Rust documentation links or explanation appreciated.
P.S. I think I understand that Rust needs to know when to destruct it but I have no idea how to make it other than just avoid making it static and pass some struct with all the regexps every time it's needed when creating the struct.
Lazily initializing and safely re-using a static variable such as a regular expression is one of the primary use-cases of the once_cell crate. Here's an example of a validation regex that is only compiled once and re-used in a struct constructor function:
use once_cell::sync::OnceCell;
use regex::Regex;
struct Struct;
impl Struct {
fn new(options: &str) -> Result<Self, &str> {
static OPTIONS_REGEX: OnceCell<Regex> = OnceCell::new();
let options_regex = OPTIONS_REGEX.get_or_init(|| {
Regex::new(r###"$(~?[\w-]+(?:=[^,]*)?(?:,~?[\w-]+(?:=[^,]*)?)*)$"###).unwrap()
});
if options_regex.is_match(options) {
Ok(Struct)
} else {
Err("invalid options")
}
}
}
playground

How to add a constraint to a field of a struct for instantiation?

I have a simple struct with one string field:
pub struct Chunk {
signature: String
}
This string field cannot be just any string, there are bunch of constraints that it needs to satisfy (and if string passed to constructor does not satisfy these constraints, construction of struct should fail).
In object-oriented languages like C++, I would make the explicit constructor that does the needed checks, what is the correct way to do this in Rust?
I came up with this code:
impl Chunk {
pub fn new(s: String) -> Option<Chunk> {
if constraints_fail {
None
} else {
Some(Chunk{signature: s})
}
}
}
I'm not sure if this is a correct approach, since technically the struct can still be instantiated with invalid string parameter without ever calling this function.
Your struct contains a private field, therefore it cannot be instantiated from outside. This is what you get if you try:
error[E0451]: field `signature` of struct `Chunk` is private
--> src/main.rs:8:24
|
8 | let _ = Chunk { signature: "xxx".to_owned() };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ private field
You don't need to do anything else - just keep the signature field private.

Writing a Rust struct type that contains a string and can be used in a constant

I'm getting started with Rust. I want to have a struct that contains (among other things) a string:
#[derive(Clone, Debug)]
struct Foo {
string_field: &str, // won't compile, but suppose String or Box<str> or &'a str or &'static str...
}
And I want to be able to declare constants or statics of it:
static FOO1: Foo = Foo {
string_field: "",
};
And I also want to be able to have it contain a string constructed at runtime:
let foo2 = Foo {
string_field: ("a".to_owned() + "b").as_str(),
};
I could add a lifetime parameter to Foo so that I can declare that the string reference has the same lifetime. That's fine, except that it then seems to require an explicit lifetime parameter for everything that contains a Foo, which means that it complicates the rest of my program (even parts that don't care about being able to use constant expressions).
I could write
enum StringOfAdequateLifetime {
Static(&'static str),
Dynamic(Box<str>), // or String, if you like
}
struct Foo {
string_field: StringOfAdequateLifetime,
}
and that seems to work so far but clutters up writing out literal Foos.
It seems obvious enough that the desired runtime behavior is sound: when you drop a Foo, drop the string it contains — and if it's static it's never dropped, so no extra information is needed to handle the two cases. Is there a clean way to ask Rust for just that?
(It seems like what I could use is some kind of "smart pointer" type to hold the string that can also be written as a constant expression for the static case, but I haven't seen one in the standard library, and when I tried to genericize StringOfAdequateLifetime to apply to any type, I ran into further complications with implementing and using the various standard traits like Deref, which I suspect were due to something about the differences between Sized and non-Sized types.)
The rust standard library has a built-in type for this exact use case, Cow. It's an enum that can represent either a reference or an owned value, and will clone the value if necessary to allow mutable access. In your particular use case, you could define the struct like so:
struct Foo {
string_field: Cow<'static, str>
}
Then you could instantiate it in one of two ways, depending on whether you want a borrowed constant string or an owned runtime-constructed value:
const BORROWED: Foo = Foo { string_field: Cow::Borrowed("some constant") };
let owned = Foo { string_field: Cow::Owned(String::from("owned string")) };
To simplify this syntax, you can define your own constructor functions for the type using a const fn to allow using the borrowed constructor in a constant context:
impl Foo {
pub const fn new_const(value: &'static str) -> Self {
Self { string_field: Cow::borrowed(value) }
}
pub fn new_runtime(value: String) -> Self {
Self { string_field: Cow::Owned(value) }
}
}
This allows you to use a simpler syntax for initializing the values:
const BORROWED: Foo = Foo::new_const("some constant");
let owned = Foo::new_runtime(String::from("owned string"));

Extracting type T from Option<T>

I have some code generated by bindgen that has function pointers represented by Option<T>.
pub type SomeFnPointerType = ::std::option::Option<
unsafe extern "C" fn ( /* .. large number of argument types .. */)
-> /* return type */
> ;
I want to store the unwrapped values in a structure. However, there are no type aliases for the inner function pointer types, so how can I define that structure? I cannot refactor the code because it's automatically generated.
I want to do something like this (in C++'ish pseudo code):
struct FunctionTable {
decltype((None as SomeFnPointerType).unwrap()) unwrappedFn;
/* ... */
};
or maybe just SomeFnPointerType::T if that is allowed.
Is it possible to achieve that in Rust? If not, the only way I see it is to manually define those types by copy-pasting code from the generated file into a separate handwritten file and keep the types in sync manually.
You can define a trait that exposes the T as an associated type.
trait OptionExt {
type Type;
}
impl<T> OptionExt for Option<T> {
type Type = T;
}
type MyOption = Option<fn()>;
fn foo(f: <MyOption as OptionExt>::Type) {
f();
}
fn main() {
foo(|| {});
}

Resources