Emmy has a big use of concepts: <https://github.com/andreaferretti/emmy>
    
    
    type
      AdditiveMonoid* = concept x, y, type T
        x + y is T
        zero(T) is T
      AdditiveGroup* = concept x, y, type T
        T is AdditiveMonoid
        -x is T
        x - y is T
      MultiplicativeMonoid* = concept x, y, type T
        x * y is T
        id(T) is T
      MultiplicativeGroup* = concept x, y, type T
        T is MultiplicativeMonoid
        x / y is T
      Ring* = concept type T
        T is AdditiveGroup
        T is MultiplicativeMonoid
      EuclideanRing* = concept x, y, type T
        T is Ring
        x div y is T
        x mod y is T
      Field* = concept type T
        T is Ring
        T is MultiplicativeGroup
    
    
    Run

And besides Arraymancer, I use this simple Hash function concept to build 
further cryptography on top of hash functions: 
<https://github.com/mratsim/constantine/blob/58d8d2c/constantine/hashes.nim#L17-L38>
    
    
    type
      CryptoHash* = concept h, var ctx, type H
        ## Interface of a cryptographic hash function
        ##
        ## - digestSizeInBytes is the hash output size in bytes
        ## - internalBlockSize, in bits:
        ##   hash functions are supposed to ingest fixed block size
        ##   that are padded if necessary
        ##   - SHA256 block size is 64 bits
        ##   - SHA512 block size is 128 bits
        ##   - SHA3-512 block size is 72 bits
        
        # should we avoid int to avoid exception? But they are compile-time
        H.digestSize is static int
        H.internalBlockSize is static int
        
        # Context
        # -------------------------------------------
        ctx.init()
        ctx.update(openarray[byte])
        ctx.finish(var array[H.digestSize, byte])
        ctx.clear()
    
    
    Run

And with all those primitives, I can create a generic `hash`
    
    
    func hash*[DigestSize: static int](
           HashKind: type CryptoHash,
           digest: var array[DigestSize, byte],
           message: openArray[byte],
           clearMem = false) {.genCharAPI.} =
      ## Produce a digest from a message
      static: doAssert DigestSize == HashKind.type.digestSize
      
      var ctx {.noInit.}: HashKind
      ctx.init()
      ctx.update(message)
      ctx.finish(digest)
      
      if clearMem:
        ctx.clear()
    
    func hash*(
           HashKind: type CryptoHash,
           message: openArray[byte],
           clearmem = false): array[HashKind.digestSize, byte] {.noInit, 
genCharAPI.} =
      ## Produce a digest from a message
      HashKind.hash(result, message, clearMem)
    
    
    Run

And then I can do `sha256.hash(message)`

Reply via email to