diff options
| author | Sakarias Johansson <sakarias.johansson@goodbyekansas.com> | 2023-01-05 17:22:10 +0100 |
|---|---|---|
| committer | Sakarias Johansson <sakarias.johansson@goodbyekansas.com> | 2023-01-05 17:22:10 +0100 |
| commit | cf7bd1aec7e9908f80bfc014fc53a1144e17ccb5 (patch) | |
| tree | d37492001d250f7dc7a1584415181ad443f62d8a | |
| download | racer-tracer-cf7bd1aec7e9908f80bfc014fc53a1144e17ccb5.tar.gz racer-tracer-cf7bd1aec7e9908f80bfc014fc53a1144e17ccb5.tar.xz racer-tracer-cf7bd1aec7e9908f80bfc014fc53a1144e17ccb5.zip | |
Initial commit 🎉
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | LICENSE | 21 | ||||
| -rw-r--r-- | default.nix | 66 | ||||
| -rw-r--r-- | nix/sources.json | 38 | ||||
| -rw-r--r-- | nix/sources.nix | 174 | ||||
| -rw-r--r-- | racer-tracer/.gitignore | 10 | ||||
| -rw-r--r-- | racer-tracer/.projectile | 0 | ||||
| -rw-r--r-- | racer-tracer/Cargo.toml | 10 | ||||
| -rw-r--r-- | racer-tracer/src/error.rs | 26 | ||||
| -rw-r--r-- | racer-tracer/src/main.rs | 78 |
10 files changed, 424 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b428354 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/release* @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Sakarias Johansson + +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. diff --git a/default.nix b/default.nix new file mode 100644 index 0000000..fe76061 --- /dev/null +++ b/default.nix @@ -0,0 +1,66 @@ +let + sources = import ./nix/sources.nix; + nixpkgs = with + { + overlay = _: pkgs: + { + niv = (import sources.niv { }).niv; + }; + }; + import sources.nixpkgs + { + overlays = [ overlay (import sources.rust) ]; + config = { }; + }; + + rustBin = nixpkgs.rust-bin.stable."1.65.0".rust; + + # rust-analyzer cannot handle symlinks + # so we need to create a derivation with the + # correct rust source without symlinks + rustSrcNoSymlinks = nixpkgs.stdenv.mkDerivation { + name = "rust-src-no-symlinks"; + + rustWithSrc = (rustBin.override { + extensions = [ "rust-src" ]; + }); + rust = rustBin; + + builder = builtins.toFile "builder.sh" '' + source $stdenv/setup + mkdir -p $out + cp -r -L $rustWithSrc/lib/rustlib/src/rust/library/. $out/ + ''; + }; +in +nixpkgs.stdenv.mkDerivation { + name = "racer-tracer"; + src = nixpkgs.nix-gitignore.gitignoreSource [] ./racer-tracer; + nativeBuildInputs = [ rustBin nixpkgs.cacert nixpkgs.xorg.libX11 ]; + configurePhase = '' + export CARGO_HOME=$PWD + ''; + + buildPhase = '' + cargo build --release + ''; + + checkPhase = '' + cargo fmt -- --check + cargo clippy + cargo test + ''; + + doCheck = true; + + installPhase = '' + mkdir -p $out/bin + find target/release -executable -type f -exec cp {} $out/bin \; + ''; + + shellHook = '' + export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${nixpkgs.lib.makeLibraryPath [ nixpkgs.xorg.libX11 nixpkgs.xorg.libXcursor ] } + #export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/lib64/ + export RUST_SRC_PATH=${rustSrcNoSymlinks} + ''; +} diff --git a/nix/sources.json b/nix/sources.json new file mode 100644 index 0000000..de0bdb3 --- /dev/null +++ b/nix/sources.json @@ -0,0 +1,38 @@ +{ + "niv": { + "branch": "master", + "description": "Easy dependency management for Nix projects", + "homepage": "https://github.com/nmattia/niv", + "owner": "nmattia", + "repo": "niv", + "rev": "351d8bc316bf901a81885bab5f52687ec8ccab6e", + "sha256": "1yzhz7ihkh6p2sxhp3amqfbmm2yqzaadqqii1xijymvl8alw5rrr", + "type": "tarball", + "url": "https://github.com/nmattia/niv/archive/351d8bc316bf901a81885bab5f52687ec8ccab6e.tar.gz", + "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz" + }, + "nixpkgs": { + "branch": "release-21.11", + "description": "Nix Packages collection", + "homepage": "", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "a7ecde854aee5c4c7cd6177f54a99d2c1ff28a31", + "sha256": "sha256:162dywda2dvfj1248afxc45kcrg83appjd0nmdb541hl7rnncf02", + "type": "tarball", + "url": "https://github.com/NixOS/nixpkgs/archive/a7ecde854aee5c4c7cd6177f54a99d2c1ff28a31.tar.gz", + "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz" + }, + "rust": { + "branch": "master", + "description": "Pure and reproducible nix overlay of binary distributed rust toolchains", + "homepage": "", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "9767af967a0becaa3bb79eeda838dbf81295eb62", + "sha256": "00jbn8c8mzhf73n8ny2j7y44m181v0vip1qjhc2qkvdv6v1wnhs6", + "type": "tarball", + "url": "https://github.com/oxalica/rust-overlay/archive/9767af967a0becaa3bb79eeda838dbf81295eb62.tar.gz", + "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz" + } +} diff --git a/nix/sources.nix b/nix/sources.nix new file mode 100644 index 0000000..1938409 --- /dev/null +++ b/nix/sources.nix @@ -0,0 +1,174 @@ +# This file has been generated by Niv. + +let + + # + # The fetchers. fetch_<type> fetches specs of type <type>. + # + + fetch_file = pkgs: name: spec: + let + name' = sanitizeName name + "-src"; + in + if spec.builtin or true then + builtins_fetchurl { inherit (spec) url sha256; name = name'; } + else + pkgs.fetchurl { inherit (spec) url sha256; name = name'; }; + + fetch_tarball = pkgs: name: spec: + let + name' = sanitizeName name + "-src"; + in + if spec.builtin or true then + builtins_fetchTarball { name = name'; inherit (spec) url sha256; } + else + pkgs.fetchzip { name = name'; inherit (spec) url sha256; }; + + fetch_git = name: spec: + let + ref = + if spec ? ref then spec.ref else + if spec ? branch then "refs/heads/${spec.branch}" else + if spec ? tag then "refs/tags/${spec.tag}" else + abort "In git source '${name}': Please specify `ref`, `tag` or `branch`!"; + in + builtins.fetchGit { url = spec.repo; inherit (spec) rev; inherit ref; }; + + fetch_local = spec: spec.path; + + fetch_builtin-tarball = name: throw + ''[${name}] The niv type "builtin-tarball" is deprecated. You should instead use `builtin = true`. + $ niv modify ${name} -a type=tarball -a builtin=true''; + + fetch_builtin-url = name: throw + ''[${name}] The niv type "builtin-url" will soon be deprecated. You should instead use `builtin = true`. + $ niv modify ${name} -a type=file -a builtin=true''; + + # + # Various helpers + # + + # https://github.com/NixOS/nixpkgs/pull/83241/files#diff-c6f540a4f3bfa4b0e8b6bafd4cd54e8bR695 + sanitizeName = name: + ( + concatMapStrings (s: if builtins.isList s then "-" else s) + ( + builtins.split "[^[:alnum:]+._?=-]+" + ((x: builtins.elemAt (builtins.match "\\.*(.*)" x) 0) name) + ) + ); + + # The set of packages used when specs are fetched using non-builtins. + mkPkgs = sources: system: + let + sourcesNixpkgs = + import (builtins_fetchTarball { inherit (sources.nixpkgs) url sha256; }) { inherit system; }; + hasNixpkgsPath = builtins.any (x: x.prefix == "nixpkgs") builtins.nixPath; + hasThisAsNixpkgsPath = <nixpkgs> == ./.; + in + if builtins.hasAttr "nixpkgs" sources + then sourcesNixpkgs + else if hasNixpkgsPath && ! hasThisAsNixpkgsPath then + import <nixpkgs> {} + else + abort + '' + Please specify either <nixpkgs> (through -I or NIX_PATH=nixpkgs=...) or + add a package called "nixpkgs" to your sources.json. + ''; + + # The actual fetching function. + fetch = pkgs: name: spec: + + if ! builtins.hasAttr "type" spec then + abort "ERROR: niv spec ${name} does not have a 'type' attribute" + else if spec.type == "file" then fetch_file pkgs name spec + else if spec.type == "tarball" then fetch_tarball pkgs name spec + else if spec.type == "git" then fetch_git name spec + else if spec.type == "local" then fetch_local spec + else if spec.type == "builtin-tarball" then fetch_builtin-tarball name + else if spec.type == "builtin-url" then fetch_builtin-url name + else + abort "ERROR: niv spec ${name} has unknown type ${builtins.toJSON spec.type}"; + + # If the environment variable NIV_OVERRIDE_${name} is set, then use + # the path directly as opposed to the fetched source. + replace = name: drv: + let + saneName = stringAsChars (c: if isNull (builtins.match "[a-zA-Z0-9]" c) then "_" else c) name; + ersatz = builtins.getEnv "NIV_OVERRIDE_${saneName}"; + in + if ersatz == "" then drv else + # this turns the string into an actual Nix path (for both absolute and + # relative paths) + if builtins.substring 0 1 ersatz == "/" then /. + ersatz else /. + builtins.getEnv "PWD" + "/${ersatz}"; + + # Ports of functions for older nix versions + + # a Nix version of mapAttrs if the built-in doesn't exist + mapAttrs = builtins.mapAttrs or ( + f: set: with builtins; + listToAttrs (map (attr: { name = attr; value = f attr set.${attr}; }) (attrNames set)) + ); + + # https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/lists.nix#L295 + range = first: last: if first > last then [] else builtins.genList (n: first + n) (last - first + 1); + + # https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/strings.nix#L257 + stringToCharacters = s: map (p: builtins.substring p 1 s) (range 0 (builtins.stringLength s - 1)); + + # https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/strings.nix#L269 + stringAsChars = f: s: concatStrings (map f (stringToCharacters s)); + concatMapStrings = f: list: concatStrings (map f list); + concatStrings = builtins.concatStringsSep ""; + + # https://github.com/NixOS/nixpkgs/blob/8a9f58a375c401b96da862d969f66429def1d118/lib/attrsets.nix#L331 + optionalAttrs = cond: as: if cond then as else {}; + + # fetchTarball version that is compatible between all the versions of Nix + builtins_fetchTarball = { url, name ? null, sha256 }@attrs: + let + inherit (builtins) lessThan nixVersion fetchTarball; + in + if lessThan nixVersion "1.12" then + fetchTarball ({ inherit url; } // (optionalAttrs (!isNull name) { inherit name; })) + else + fetchTarball attrs; + + # fetchurl version that is compatible between all the versions of Nix + builtins_fetchurl = { url, name ? null, sha256 }@attrs: + let + inherit (builtins) lessThan nixVersion fetchurl; + in + if lessThan nixVersion "1.12" then + fetchurl ({ inherit url; } // (optionalAttrs (!isNull name) { inherit name; })) + else + fetchurl attrs; + + # Create the final "sources" from the config + mkSources = config: + mapAttrs ( + name: spec: + if builtins.hasAttr "outPath" spec + then abort + "The values in sources.json should not have an 'outPath' attribute" + else + spec // { outPath = replace name (fetch config.pkgs name spec); } + ) config.sources; + + # The "config" used by the fetchers + mkConfig = + { sourcesFile ? if builtins.pathExists ./sources.json then ./sources.json else null + , sources ? if isNull sourcesFile then {} else builtins.fromJSON (builtins.readFile sourcesFile) + , system ? builtins.currentSystem + , pkgs ? mkPkgs sources system + }: rec { + # The sources, i.e. the attribute set of spec name to spec + inherit sources; + + # The "pkgs" (evaluated nixpkgs) to use for e.g. non-builtin fetchers + inherit pkgs; + }; + +in +mkSources (mkConfig {}) // { __functor = _: settings: mkSources (mkConfig settings); } diff --git a/racer-tracer/.gitignore b/racer-tracer/.gitignore new file mode 100644 index 0000000..767dae2 --- /dev/null +++ b/racer-tracer/.gitignore @@ -0,0 +1,10 @@ +# Generated by Cargo +# will have compiled files and executables +target/ + +# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries +# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html +Cargo.lock + +# These are backup files generated by rustfmt +**/*.rs.bk diff --git a/racer-tracer/.projectile b/racer-tracer/.projectile new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/racer-tracer/.projectile diff --git a/racer-tracer/Cargo.toml b/racer-tracer/Cargo.toml new file mode 100644 index 0000000..e764f79 --- /dev/null +++ b/racer-tracer/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "racer-tracer" +version = "0.1.0" +authors = ["Sakarias Johansson <sakarias.johansson@goodbyekansas.com>"] +edition = "2021" + +[dependencies] +minifb = "0.23" +tokio = { version = "1.14.0", features = ["macros", "rt", "rt-multi-thread"] } +thiserror = "1" diff --git a/racer-tracer/src/error.rs b/racer-tracer/src/error.rs new file mode 100644 index 0000000..f581b08 --- /dev/null +++ b/racer-tracer/src/error.rs @@ -0,0 +1,26 @@ +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum TracerError { + #[error("Unknown error: {message}")] + Unknown { message: String, exit_code: i32 }, + + #[error("Failed to create window: {0}")] + FailedToCreateWindow(String), + + #[error("Failed to update window: {0}")] + FailedToUpdateWindow(String), +} + +impl From<TracerError> for i32 { + fn from(tracer_error: TracerError) -> Self { + match tracer_error { + TracerError::Unknown { + message: _, + exit_code, + } => exit_code, + TracerError::FailedToCreateWindow(_) => 2, + TracerError::FailedToUpdateWindow(_) => 3, + } + } +} diff --git a/racer-tracer/src/main.rs b/racer-tracer/src/main.rs new file mode 100644 index 0000000..959ea0a --- /dev/null +++ b/racer-tracer/src/main.rs @@ -0,0 +1,78 @@ +#[macro_use] +mod error; + +use minifb::{Key, Window, WindowOptions}; + +fn hsv_to_rgb(H: f64, S: f64, V: f64) -> u32 { + let s: f64 = S / 100.0; + let v: f64 = V / 100.0; + let C: f64 = s * v; + let mut A: f64 = H / 60.0; + A %= 2.0f64; + let X: f64 = C * (1f64 - (A - 1f64).abs()); + let m: f64 = v - C; + + let mut r: f64; + let mut g: f64; + let mut b: f64; + if H >= 0.0 && H < 60.0 { + r = C; + g = X; + b = 0.0; + } else if H >= 60.0 && H < 120.0 { + r = X; + g = C; + b = 0.0; + } else if H >= 120.0 && H < 180.0 { + r = 0.0; + g = C; + b = X; + } else if H >= 180.0 && H < 240.0 { + r = 0.0; + g = X; + b = C; + } else if H >= 240.0 && H < 300.0 { + r = X; + g = 0.0; + b = C; + } else { + r = C; + g = 0.0; + b = X; + } + + let red: u32 = ((r + m) * 255.0) as u32; + let green: u32 = ((g + m) * 255.0) as u32; + let blue: u32 = ((b + m) * 255.0) as u32; + ((red as u32) << 16) | ((green as u32) << 8) | blue as u32 +} + +async fn run(width: usize, height: usize) -> Result<(), error::TracerError> { + let mut screen_buffer: Vec<u32> = vec![0; width * height]; + let mut window = Window::new("racer-tracer", width, height, WindowOptions::default()) + .expect("Unable to create window"); + window.limit_update_rate(Some(std::time::Duration::from_micros(16600))); + + let mut count = 1; + while window.is_open() && !window.is_key_down(Key::Escape) { + count = (count + 1) % 360; + let color = hsv_to_rgb(count as f64, 100.0, 100.0); + for i in screen_buffer.iter_mut() { + *i = color; + } + + window + .update_with_buffer(&screen_buffer, width, height) + .map_err(|e| error::TracerError::FailedToUpdateWindow(e.to_string()))?; + } + + Ok(()) +} + +#[tokio::main] +async fn main() { + if let Err(e) = run(640, 480).await { + eprintln!("{}", e); + std::process::exit(e.into()) + } +} |
