Skip to content

Commit

Permalink
Update: safety of lexical::WriteFloatOptions::builder().build_uncheck…
Browse files Browse the repository at this point in the history
…ed()
  • Loading branch information
Graham Enos committed Jun 2, 2022
1 parent 15b79a3 commit f11c9e3
Showing 1 changed file with 29 additions and 13 deletions.
42 changes: 29 additions & 13 deletions src/expression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use lexical::{format, to_string_with_options, WriteFloatOptions};
use num_complex::Complex64;
use std::collections::{hash_map::DefaultHasher, HashMap};
use std::f64::consts::PI;
Expand Down Expand Up @@ -436,27 +437,42 @@ impl<'a> FromStr for Expression {
/// - When both are non-zero, show with the correct operator in between
#[inline(always)]
fn format_complex(value: &Complex64) -> String {
const FORMAT: u128 = lexical::format::STANDARD;
let options = lexical::WriteFloatOptions::builder()
.negative_exponent_break(NonZeroI32::new(-5))
.positive_exponent_break(NonZeroI32::new(15))
.trim_floats(true)
.build()
.unwrap();
const FORMAT: u128 = format::STANDARD;
// Safety:
// This uses `build_unchecked`, which is safe as long as `is_valid` is true, and
// `is_valid` must be true because we don't change the default values for:
// - the exponent string,
// - the decimal point,
// - the NaN string,
// - the ∞ string,
// - or the minimum or maximum significant digits.
// Of what we _do_ change:
// - negative_exponent_break is < 0
// - positive_exponent_break is > 0
// - trim floats can only take a bool and both branches are safe.
// As of version 6.1.1 of lexical, this means `OPTIONS.is_valid()` must be true. However, we
// still `assert!` it just to be "safe."
const OPTIONS: WriteFloatOptions = unsafe {
let options = WriteFloatOptions::builder()
.negative_exponent_break(NonZeroI32::new(-5))
.positive_exponent_break(NonZeroI32::new(15))
.trim_floats(true)
.build_unchecked();
assert!(options.is_valid());
options
};
if value.re == 0f64 && value.im == 0f64 {
"0".to_owned()
} else if value.im == 0f64 {
lexical::to_string_with_options::<_, FORMAT>(value.re, &options)
to_string_with_options::<_, FORMAT>(value.re, &OPTIONS)
} else if value.re == 0f64 {
lexical::to_string_with_options::<_, FORMAT>(value.im, &options) + "i"
to_string_with_options::<_, FORMAT>(value.im, &OPTIONS) + "i"
} else {
let mut out = lexical::to_string_with_options::<_, FORMAT>(value.re, &options);
let mut out = to_string_with_options::<_, FORMAT>(value.re, &OPTIONS);
if value.im > 0f64 {
out.push('+')
}
out.push_str(&lexical::to_string_with_options::<_, FORMAT>(
value.im, &options,
));
out.push_str(&to_string_with_options::<_, FORMAT>(value.im, &OPTIONS));
out.push('i');
out
}
Expand Down

0 comments on commit f11c9e3

Please sign in to comment.