BTW I think some anti-Rust people are more annoying than the worst Rust evangelists - seen some of them calling people not using Rust as “murderers”, because “memory leakage can kill at the right time” - but that’s due to them being evangelists to right-wing politics.

  • Err(()).unwrap()@lemmy.world
    link
    fedilink
    arrow-up
    2
    ·
    11 hours ago

    "We spent two decades making sure the compiler will never produce memory-unsafe code. It requires a lot of nigh-illegible boilerplate code to even compile and adds massive cognitive load, but the effort will be worth it.

    Anyway, here’s a type whose only purpose is to disable all of that shit."

    • jjj@lemmy.blahaj.zone
      link
      fedilink
      arrow-up
      2
      ·
      5 hours ago

      Cell doesn’t disable memory safety, though? It comes with additional restrictions such as being unable to share between threads (statically enforced) obviously, it’s not an unsafe feature. You also can’t read from it unless your type can be bitwise copied, etc.

      Interior mutability is mostly for making immutable interfaces that for some reason or another benefit from storing a bit of mutable state, such as for lazy evaluation. It’s also used for cross thread communication in some cases since you have to use shared (immutable) references to share things between threads.

      It requires a lot of nigh-illegible boilerplate code to even compile

      this is the entire source code for an app that performs a rather complex function, note the absence of boilerplate

      from https://codeberg.org/Mycellf/wordjoin

      use std::{
          fs::File,
          io::{self, BufRead, BufReader, Read, Write},
          path::PathBuf,
      };
      
      use clap::{Parser, ValueEnum};
      use icu_segmenter::{
          LineSegmenter, LineSegmenterBorrowed,
          options::{LineBreakOptions, LineBreakStrictness, LineBreakWordOption},
      };
      
      /// Insert utf-8 word joiners (U+2060) to prevent text from wrapping outside of whitespace characters.
      #[derive(Parser)]
      struct Args {
          /// Format and concatenate each file in stead of stdin
          file_paths: Vec<PathBuf>,
      
          /// Read stdin by line instead of all at once
          /// (sometimes worse for interactive use; files are always read by line)
          #[clap(short = 'l', long)]
          by_line: bool,
      
          /// See https://drafts.csswg.org/css-text-3/#line-break-property
          #[clap(short, long, default_value = "strict")]
          strictness: LineBreakStrictnessValues,
          /// See https://drafts.csswg.org/css-text-3/#word-break-property
          #[clap(short, long, default_value = "normal")]
          word_option: LineBreakWordOptionValues,
      
          /// Print this app's GNU GPL-3.0 license
          #[arg(short = 'L', long)]
          license: bool,
      
          /// Print this app's source code
          #[arg(short = 'S', long)]
          source: bool,
      }
      
      const WORD_JOINER: char = '\u{2060}';
      
      fn main() -> io::Result<()> {
          let args = Args::parse();
      
          if args.source || args.license {
              if args.source {
                  println!(
                      "Cargo.toml:\n{config}\n\nsrc/main.rs:\n{source}\n\nREADME.md:\n{readme}",
                      config = include_str!("../Cargo.toml"),
                      source = include_str!("main.rs"),
                      readme = include_str!("../README.md"),
                  );
              }
      
              if args.license {
                  println!("LICENSE:\n{}", include_str!("../LICENSE"));
              }
      
              return Ok(());
          }
      
          let mut options = LineBreakOptions::default();
          options.strictness = Some(args.strictness.into());
          options.word_option = Some(args.word_option.into());
      
          let segmenter = LineSegmenter::new_auto(options);
      
          let mut stdout = io::stdout().lock();
      
          if args.file_paths.is_empty() {
              let stdin = io::stdin();
      
              if args.by_line {
                  join_text_by_lines(stdout, stdin, segmenter)?;
              } else {
                  join_text_by_all(stdout, stdin, segmenter)?;
              }
          } else {
              for path in args.file_paths {
                  let file = File::open(path)?;
      
                  join_text_by_lines(&mut stdout, file, segmenter)?;
              }
          }
      
          Ok(())
      }
      
      fn join_text_by_lines(
          mut writer: impl Write,
          text: impl Read,
          segmenter: LineSegmenterBorrowed,
      ) -> io::Result<()> {
          for line in BufReader::new(text).lines() {
              let line = line?;
      
              join_text(&mut writer, &line, segmenter)?;
              writeln!(&mut writer)?;
          }
      
          Ok(())
      }
      
      fn join_text_by_all(
          writer: impl Write,
          mut text: impl Read,
          segmenter: LineSegmenterBorrowed,
      ) -> io::Result<()> {
          let mut input = String::new();
          text.read_to_string(&mut input)?;
      
          join_text(writer, &input, segmenter)?;
      
          Ok(())
      }
      
      fn join_text(
          mut writer: impl Write,
          text: &str,
          segmenter: LineSegmenterBorrowed,
      ) -> io::Result<()> {
          let mut segments = segmenter.segment_str(text).peekable();
      
          while let (Some(start), Some(&end)) = (segments.next(), segments.peek()) {
              let segment = &text[start..end];
      
              write!(writer, "{segment}")?;
      
              if end < text.len()
                  && segment
                      .chars()
                      .next_back()
                      .is_some_and(|end| !end.is_whitespace())
              {
                  write!(writer, "{WORD_JOINER}")?;
              }
          }
      
          Ok(())
      }
      
      #[derive(Clone, ValueEnum)]
      enum LineBreakStrictnessValues {
          Loose,
          Normal,
          Strict,
          Anywhere,
      }
      
      impl From<LineBreakStrictnessValues> for LineBreakStrictness {
          fn from(value: LineBreakStrictnessValues) -> Self {
              match value {
                  LineBreakStrictnessValues::Loose => LineBreakStrictness::Loose,
                  LineBreakStrictnessValues::Normal => LineBreakStrictness::Normal,
                  LineBreakStrictnessValues::Strict => LineBreakStrictness::Strict,
                  LineBreakStrictnessValues::Anywhere => LineBreakStrictness::Anywhere,
              }
          }
      }
      
      #[derive(Clone, ValueEnum)]
      enum LineBreakWordOptionValues {
          Normal,
          BreakAll,
          KeepAll,
      }
      
      impl From<LineBreakWordOptionValues> for LineBreakWordOption {
          fn from(value: LineBreakWordOptionValues) -> Self {
              match value {
                  LineBreakWordOptionValues::Normal => LineBreakWordOption::Normal,
                  LineBreakWordOptionValues::BreakAll => LineBreakWordOption::BreakAll,
                  LineBreakWordOptionValues::KeepAll => LineBreakWordOption::KeepAll,
              }
          }
      }