From 959a2ef8369368b4ca532e39835e27e81294dbfd Mon Sep 17 00:00:00 2001 From: Jakob Nybo Nissen Date: Thu, 23 Oct 2025 13:46:27 +0200 Subject: [PATCH] Allow creating a BAMCIGAR from existing memory. --- Project.toml | 2 +- docs/src/index.md | 1 + docs/src/reference.md | 1 + src/CIGARStrings.jl | 2 +- src/bamcigar.jl | 38 +++++++++++++++++++++++++++++++++++--- 5 files changed, 39 insertions(+), 5 deletions(-) diff --git a/Project.toml b/Project.toml index 33f8d61..ce26838 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "CIGARStrings" uuid = "e5b51f81-6ffd-4e20-bbec-f118e37ea906" -version = "0.1.4" +version = "0.1.5" authors = ["Jakob Nybo Nissen "] [deps] diff --git a/docs/src/index.md b/docs/src/index.md index f209435..ba56fe1 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -236,6 +236,7 @@ However, in order to make zero-copy CIGARs possible, the `BAMCIGAR` type is back ```@docs CIGARStrings.BAMCIGAR +CIGARStrings.BAMCIGAR(::MutableMemoryView{UInt8}, ::CIGAR) ``` A `BAMCIGAR` can be constructed from its binary representation, using any type which implements `MemoryViews.MemoryView`: diff --git a/docs/src/reference.md b/docs/src/reference.md index 53383df..e786a32 100644 --- a/docs/src/reference.md +++ b/docs/src/reference.md @@ -10,6 +10,7 @@ end ```@docs; canonical = false CIGAR +BAMCIGAR CIGARElement CIGAROp Translation diff --git a/src/CIGARStrings.jl b/src/CIGARStrings.jl index b20e62f..ab19844 100644 --- a/src/CIGARStrings.jl +++ b/src/CIGARStrings.jl @@ -11,7 +11,7 @@ export CIGAR, public CIGARError, CIGARErrorType, Errors, try_parse, outside, pos, gap, TranslationKind, PositionMapper -using MemoryViews: MemoryViews, ImmutableMemoryView, MemoryView +using MemoryViews: MemoryViews, ImmutableMemoryView, MemoryView, MutableMemoryView struct Unsafe end const unsafe = Unsafe() diff --git a/src/bamcigar.jl b/src/bamcigar.jl index e62781f..86c38ae 100644 --- a/src/bamcigar.jl +++ b/src/bamcigar.jl @@ -14,7 +14,8 @@ stored compactly in 32-bit integers. Semantically, a BAMCIGAR behaves much similar to a CIGAR. Construct a BAMCIGAR either from a CIGAR, taking an optional `Vector{UInt8}` -to use as backing storage, or using [`CIGARStrings.try_parse`](@ref). +to use as backing storage, or using [`CIGARStrings.try_parse`](@ref), +or [`BAMCIGAR(::MutableMemoryView{UInt8}, ::CIGAR)`](@ref) # Examples ```jldoctest @@ -135,20 +136,51 @@ function cigar_view!(v::Vector{UInt8}, x::BAMCIGAR) end BAMCIGAR(x::CIGAR) = BAMCIGAR(x, UInt8[]) + function BAMCIGAR(x::CIGAR, v::Vector{UInt8}) resize!(v, 4 * length(x)) + return @inbounds BAMCIGAR(MemoryView(v), x) +end + +""" + BAMCIGAR(mem::MutableMemoryView{UInt8}, x::CIGAR)::BAMCIGAR + +Construct a `BAMCIGAR` equal to `x`, using the memory `mem`. +After calling this, `mem` may not be mutated, and is considered +owned by the resulting `BAMCIGAR`. + +Throw a `BoundsError` if `length(mem) < 4 * length(x)`. + +# Examples +```jldoctest +julia> x = CIGAR("150M3D9S"); + +julia> mem = MemoryView(zeros(UInt8, 15)); + +julia> cigar = BAMCIGAR(mem, x) +BAMCIGAR(CIGAR("150M3D9S")) + +julia> parent(MemoryView(cigar)) === parent(mem) +true +``` +""" +function BAMCIGAR(mem::MutableMemoryView{UInt8}, x::CIGAR) + @boundscheck if length(mem) < 4 * length(x) + throw(BoundsError(mem, 4 * length(x))) + end + mem = @inbounds mem[1:(4 * length(x))] i = 1 for element in x u = getfield(element, :x) for _ in 1:4 - @inbounds v[i] = u % UInt8 + @inbounds mem[i] = u % UInt8 i += 1 u >>= 8 end end return BAMCIGAR( unsafe, - ImmutableMemoryView(v), + ImmutableMemoryView(mem), x.aln_len, x.ref_len, x.query_len