Code Monkey home page Code Monkey logo

bites's Introduction

bites

What

A no-brainer Clojure library for easily turning (certain) things into bytes (and back), which you can wrap your head around in less than 15 minutes. Emphasis is on correctness rather than speed (i.e. byte arrays/buffers are not reused). Generative testing through test.check, and where appropriate against commons-codec.

Why

Every once in a while I'm finding myself looking online about how to turn certain objects into bytes, and I've done it so many times now that I am starting to memorize the various articles/posts I encounter over and over again. Yes, commons-codec and byte-streams do exist, but they are heavy-weight candidates and rather grander in terms of scope. Ideally, I would like a lightweight (dependency-free), Clojure-native solution.

Where

Clojars Project

Usage

The focus is on the following objects (followed by an optional map), but there are abstractions for everything.

  • java.lang.Integer
  • java.lang.Long
  • java.lang.Double
  • java.math.BigInteger
  • java.math.BigDecimal
  • java.lang.String - {:encoding (or string? charset? #{:b2 :b8 :b16 :b64 :uuid}) :b64-flavor #{:mime :url}}
  • java.util.UUID
  • java.io.InputStream - {:buffer-size pos-int?}
  • java.io.File - {:buffer-size pos-int?}
  • java.net.URL - {:buffer-size pos-int?}
  • java.net.URI - {:buffer-size pos-int?}
  • java.awt.image.BufferedImage - {:buffer-size pos-int? :image-type string?}
  • java.nio.ByteBuffer
  • java.nio.channels.ReadableByteChannel - {:buffer-size pos-int?}
  • java.io.Serializable

One could argue that java.lang.String deserves extra attention, as it can represent various encodings (e.g. unicode, baseN, uuid etc).

bites.core/to-bytes [x ?opts]

Turns any of the aforementioned classes to a byte-array. A mere wrapper around bites.convert/toBytes. opts are optional and not even needed most of the times (see list above). For example:

(let [uid (UUID/randomUUID)] 
  (= (to-bytes uid nil)
     ;; the bytes of a UUID object match with the bytes
     ;; of the String representation of that object
     (to-bytes (str uid) {:encoding :uuid}))) ;; => true

bites.core/from-bytes [klass bs ?opts]

The opposite of to-bytes. Returns an instance of klass given bytes bs and opts. A mere wrapper around bites.convert/fromBytes, and as such may require type-hinting at the call site. java.io.File, java.net.URL and java.net.URI don't participate in this. Moreover,java.io.Serializable is hardly useful as klass in this context. It will do the right thing, but you need to know the concrete type in order to do anything useful with the result, and if you know the actual type, then you're better off providing custom to/from impls for it.

(let [uid (to-bytes (UUID/randomUUID) nil)] 
  (= (str (from-bytes uid nil))
     ;; the bytes of a UUID object match with the bytes
     ;; of the String representation of that object
     (from-bytes String uid {:encoding :uuid}))) ;; => true

bites.core/def-from [name doc-string klass]

Defines a type-hinted version of from-bytes (according to klass), taking one or two args (as opposed to three). For example:

(def-from bytes->string  ;; define it
  "bytes-to-string converter" 
  String) 

(-> (.getBytes "hi there")
    (bytes->string  nil) ;; use it
    (.substring 0 2))    ;; no reflection 

 => "hi"

bites.io

This namespace contains NIO extensions of clojure.java.io. It provides its own copy fn, because (unfortunately) the clojure.java.io/do-copy one is private. The good news is that bites.io/do-copy will delegate to clojure.java.io/do-copy for anything it doesn't recognise. More specifically...

clojure.java.io/IOFactory

This is extended (where appropriate) to ByteBuffer, ReadableByteChannel and WritableByteChannel.

bites.io/copy

In addition to anything supported by clojure.java.io/copy, this will also work against the following:

  • ByteBuffer => OutputStream/Writer/File/WritableByteChannel
  • Reader/String/chars/bytes => WritableByteChannel
  • ReadableByteChannel => OutputStream/Writer/File/ByteBuffer/WritableByteChannel
  • InputStream => WritableByteChannel
  • File => WritableByteChannel

bites.exchange

This namespace provides two different producer/consumer models. One is the well-known (one-directional) asynchronous-queueing model, and the other is the (bi-directional) synchronous-exchange model. The former is good for cases where producing is completely independent from consuming, whereas the latter shines in situations where what will be produced depends on the outcome of consumption (excluding the very first round), and as such requires a synchronous hand-off.

Limitations

to-bytes/from-bytes returns/expects a single byte-array. This means that the usual limitations of the JVM with respect to array sizes apply here too. More specifically, array-indexing using 32-bit integers means that ~2GB is the maximum possible size (i.e. don't expect to be able to read something larger than that into a single byte-array).

See rapio for reading local resources larger than 2GB into a sequence of byte-arrays.

Requirements

  • Java 11+
  • Clojure 1.9+

License

Copyright © 2020 Dimitrios Piliouras

This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0.

This Source Code may also be made available under the following Secondary Licenses when the conditions for such availability set forth in the Eclipse Public License, v. 2.0 are satisfied: GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version, with the GNU Classpath Exception which is available at https://www.gnu.org/software/classpath/license.html.

bites's People

Contributors

jimpil avatar

Stargazers

 avatar  avatar  avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.