lib/polars/binary_name_space.rb



module Polars
  # Series.bin namespace.
  class BinaryNameSpace
    include ExprDispatch

    self._accessor = "bin"

    # @private
    def initialize(series)
      self._s = series._s
    end

    # Check if binaries in Series contain a binary substring.
    #
    # @param literal [String]
    #   The binary substring to look for
    #
    # @return [Series]
    #
    # @example
    #   s = Polars::Series.new("colors", ["\x00\x00\x00".b, "\xff\xff\x00".b, "\x00\x00\xff".b])
    #   s.bin.contains("\xff".b)
    #   # =>
    #   # shape: (3,)
    #   # Series: 'colors' [bool]
    #   # [
    #   #         false
    #   #         true
    #   #         true
    #   # ]
    def contains(literal)
      super
    end

    # Check if string values end with a binary substring.
    #
    # @param suffix [String]
    #   Suffix substring.
    #
    # @return [Series]
    #
    # @example
    #   s = Polars::Series.new("colors", ["\x00\x00\x00".b, "\xff\xff\x00".b, "\x00\x00\xff".b])
    #   s.bin.ends_with("\x00".b)
    #   # =>
    #   # shape: (3,)
    #   # Series: 'colors' [bool]
    #   # [
    #   #         true
    #   #         true
    #   #         false
    #   # ]
    def ends_with(suffix)
      super
    end

    # Check if values start with a binary substring.
    #
    # @param prefix [String]
    #   Prefix substring.
    #
    # @return [Series]
    #
    # @example
    #   s = Polars::Series.new("colors", ["\x00\x00\x00".b, "\xff\xff\x00".b, "\x00\x00\xff".b])
    #   s.bin.starts_with("\x00".b)
    #   # =>
    #   # shape: (3,)
    #   # Series: 'colors' [bool]
    #   # [
    #   #         true
    #   #         false
    #   #         true
    #   # ]
    def starts_with(prefix)
      super
    end

    # Decode a value using the provided encoding.
    #
    # @param encoding ["hex", "base64"]
    #   The encoding to use.
    # @param strict [Boolean]
    #   Raise an error if the underlying value cannot be decoded,
    #   otherwise mask out with a null value.
    #
    # @return [Series]
    #
    # @example Decode values using hexadecimal encoding.
    #   s = Polars::Series.new("colors", ["000000".b, "ffff00".b, "0000ff".b])
    #   s.bin.decode("hex")
    #   # =>
    #   # shape: (3,)
    #   # Series: 'colors' [binary]
    #   # [
    #   #         b"\x00\x00\x00"
    #   #         b"\xff\xff\x00"
    #   #         b"\x00\x00\xff"
    #   # ]
    #
    # @example Decode values using Base64 encoding.
    #   s = Polars::Series.new("colors", ["AAAA".b, "//8A".b, "AAD/".b])
    #   s.bin.decode("base64")
    #   # =>
    #   # shape: (3,)
    #   # Series: 'colors' [binary]
    #   # [
    #   #         b"\x00\x00\x00"
    #   #         b"\xff\xff\x00"
    #   #         b"\x00\x00\xff"
    #   # ]
    #
    # @example Set `strict: false` to set invalid values to null instead of raising an error.
    #   s = Polars::Series.new("colors", ["000000".b, "ffff00".b, "invalid_value".b])
    #   s.bin.decode("hex", strict: false)
    #   # =>
    #   # shape: (3,)
    #   # Series: 'colors' [binary]
    #   # [
    #   #         b"\x00\x00\x00"
    #   #         b"\xff\xff\x00"
    #   #         null
    #   # ]
    def decode(encoding, strict: true)
      super
    end

    # Encode a value using the provided encoding.
    #
    # @param encoding ["hex", "base64"]
    #   The encoding to use.
    #
    # @return [Series]
    #
    # @example Encode values using hexadecimal encoding.
    #   s = Polars::Series.new("colors", ["\x00\x00\x00".b, "\xff\xff\x00".b, "\x00\x00\xff".b])
    #   s.bin.encode("hex")
    #   # =>
    #   # shape: (3,)
    #   # Series: 'colors' [str]
    #   # [
    #   #         "000000"
    #   #         "ffff00"
    #   #         "0000ff"
    #   # ]
    #
    # @example Encode values using Base64 encoding.
    #   s.bin.encode("base64")
    #   # =>
    #   # shape: (3,)
    #   # Series: 'colors' [str]
    #   # [
    #   #         "AAAA"
    #   #         "//8A"
    #   #         "AAD/"
    #   # ]
    def encode(encoding)
      super
    end

    # Get the size of the binary values in a Series in the given unit.
    #
    # @return [Series]
    #
    # @example
    #   s = Polars::Series.new("data", [512, 256, 2560, 1024].map { |n| "\x00".b * n })
    #   s.bin.size("kb")
    #   # =>
    #   # shape: (4,)
    #   # Series: 'data' [f64]
    #   # [
    #   #         0.5
    #   #         0.25
    #   #         2.5
    #   #         1.0
    #   # ]
    def size(unit = "b")
      super
    end

    # Interpret a buffer as a numerical polars type.
    #
    # @param dtype [Object]
    #   Which type to interpret binary column into.
    # @param endianness ["big", "little"]
    #   Which endianness to use when interpreting bytes, by default "little".
    #
    # @return [Series]
    #
    # @example
    #   s = Polars::Series.new("data", ["\x05\x00\x00\x00".b, "\x10\x00\x01\x00".b])
    #   s.bin.reinterpret(dtype: Polars::Int32, endianness: "little")
    #   # =>
    #   # shape: (2,)
    #   # Series: 'data' [i32]
    #   # [
    #   #         5
    #   #         65552
    #   # ]
    def reinterpret(dtype:, endianness: "little")
      super
    end

    # Slice the binary values.
    #
    # @param offset [Object]
    #   Start index. Negative indexing is supported.
    # @param length [Object]
    #   Length of the slice. If set to `nil` (default), the slice is taken to the
    #   end of the value.
    #
    # @return [Series]
    #
    # @example
    #   colors = Polars::Series.new(["\x00\x00\x00".b, "\xff\xff\x00".b, "\x00\x00\xff".b])
    #   colors.bin.slice(1, 2)
    #   # =>
    #   # shape: (3,)
    #   # Series: '' [binary]
    #   # [
    #   #         b"\x00\x00"
    #   #         b"\xff\x00"
    #   #         b"\x00\xff"
    #   # ]
    def slice(offset, length = nil)
      super
    end

    # Take the first `n` bytes of the binary values.
    #
    # @param n [Object]
    #   Length of the slice. Negative indexing is supported; see note (2) below.
    #
    # @return [Series]
    #
    # @note
    #   (1) A similar method exists for taking the last `n` bytes: `tail`.
    #   (2) If `n` is negative, it is interpreted as "until the nth byte from the end",
    #       e.g., `head(-3)` returns all but the last three bytes.
    #
    # @example
    #   colors = Polars::Series.new(["\x00\x00\x00".b, "\xff\xff\x00".b, "\x00\x00\xff".b])
    #   colors.bin.head(2)
    #   # =>
    #   # shape: (3,)
    #   # Series: '' [binary]
    #   # [
    #   #         b"\x00\x00"
    #   #         b"\xff\xff"
    #   #         b"\x00\x00"
    #   # ]
    def head(n = 5)
      super
    end

    # Take the last `n` bytes of the binary values.
    #
    # @param n [Object]
    #   Length of the slice. Negative indexing is supported; see note (2) below.
    #
    # @return [Series]
    #
    # @note
    #   (1) A similar method exists for taking the first `n` bytes: `head`.
    #   (2) If `n` is negative, it is interpreted as "starting at the nth byte",
    #       e.g., `tail(-3)` returns all but the first three bytes.
    #
    # @example
    #   colors = Polars::Series.new(["\x00\x00\x00".b, "\xff\xff\x00".b, "\x00\x00\xff".b])
    #   colors.bin.tail(2)
    #   # =>
    #   # shape: (3,)
    #   # Series: '' [binary]
    #   # [
    #   #         b"\x00\x00"
    #   #         b"\xff\x00"
    #   #         b"\x00\xff"
    #   # ]
    def tail(n = 5)
      super
    end
  end
end