<commit_before>#pragma once

#include <estd/string.h>
#include <coap/platform.h>
#include <coap/encoder.hpp>
#include <coap/decoder.h>
#include <coap/decoder/netbuf.h>
#include <coap/context.h>
#include <coap/observable.h>
#include "coap-uint.h"
#include <mc/memory-chunk.h>
#include "exp/datapump.h"

#include <chrono>


// Basically working, however first enqueued message mysteriously disappears
template <class TDataPump, class TObservableCollection>
void evaluate_emit_observe(TDataPump& datapump,
                           moducom::coap::ObservableRegistrar<TObservableCollection>& observable_registrar,
                           std::chrono::milliseconds total_since_start)
{
    using namespace moducom::coap;
    typedef typename TDataPump::netbuf_t netbuf_t;
    typedef typename TDataPump::addr_t addr_t;
    typedef moducom::pipeline::MemoryChunk::readonly_t ro_chunk_t;
    typedef typename TObservableCollection::iterator iterator;

    static std::chrono::milliseconds last(0);

    std::chrono::milliseconds elapsed = total_since_start - last;

    if(elapsed.count() > 1000)
    {
        last = total_since_start;

        iterator it = observable_registrar.begin();

        while(it != observable_registrar.end())
        {
            //std::clog << "Sending to " << addr << std::endl;
            std::clog << "Event fired" << std::endl;

#ifdef FEATURE_MCCOAP_DATAPUMP_INLINE
            NetBufEncoder<netbuf_t> encoder;
#else
            NetBufEncoder<netbuf_t&> encoder(* new netbuf_t);
#endif

            static int mid = 0;

            // we want a NON or CON since observer messages are not a normal response
            // but instead classified as 'notifications'
            Header header(Header::NonConfirmable, Header::Code::Content);

            addr_t addr = (*it).addr;
            const layer2::Token& token = (*it).token;
            // NOTE: it appears coap-cli doesn't like a sequence # of 0
            int sequence = ++(*it).sequence;
            ++it;

            header.message_id(mid++);
            header.token_length(token.length());

            encoder.header(header);
            encoder.token(token);
            encoder.option(Option::Observe, sequence); // using mid also for observe counter since we aren't doing CON it won't matter

            // zero-copy goodness
            // NOTE: Does not account for chunking, and that would be involved since
            // snprintf doesn't indicate whether things got truncated
            int advance_by = snprintf(
                    (char*)encoder.payload(), encoder.size(),
                    "Observed: %d", sequence);

            encoder.advance(advance_by);

            /* this way works too!
             *

            estd::layer3::basic_string<char, false> s(0, (char*)encoder.data(), encoder.size());

            s += "Observed: ";
            s += estd::to_string(header.message_id());

            encoder.advance(s.size());
             */

            encoder.complete();

#ifdef FEATURE_MCCOAP_DATAPUMP_INLINE
            datapump.enqueue_out(std::forward<netbuf_t>(encoder.netbuf()), addr);
#else
            datapump.enqueue_out(encoder.netbuf(), addr);<commit_msg>Code organization<commit_after>#pragma once

#include <estd/string.h>
#include <coap/platform.h>
#include <coap/encoder.hpp>
#include <coap/decoder.h>
#include <coap/decoder/netbuf.h>
#include <coap/context.h>
#include <coap/observable.h>
#include "coap-uint.h"
#include <mc/memory-chunk.h>
#include "exp/datapump.h"

#include <chrono>


template <class TNetBuf>
#ifdef FEATURE_MCCOAP_DATAPUMP_INLINE
void emit_observe(moducom::coap::NetBufEncoder<TNetBuf>& encoder, int sequence)
#else
void emit_observe(moducom::coap::NetBufEncoder<TNetBuf&>& encoder, int sequence)
#endif
{
    // breaking this out thinking maybe some day we can actually genericize evaluate_emit_observe
    // though would be tricky for early-appearing options

    // zero-copy goodness
    // NOTE: Does not account for chunking, and that would be involved since
    // snprintf doesn't indicate whether things got truncated
    int advance_by = snprintf(
            (char*)encoder.payload(), encoder.size(),
            "Observed: %d", sequence);

    encoder.advance(advance_by);

    /* this way works too!
     *

    estd::layer3::basic_string<char, false> s(0, (char*)encoder.data(), encoder.size());

    s += "Observed: ";
    s += estd::to_string(header.message_id());

    encoder.advance(s.size());
     */
}


// TODO: pass in emit and emit_pre, pre being a NULLPTR default fn ptr for options which need to happen
// *before* Observe (6)
template <class TDataPump, class TObservableCollection>
void emit_observe_helper(TDataPump& datapump,
                         moducom::coap::ObservableRegistrar<TObservableCollection>& observable_registrar)
{

}

// Basically working, however first enqueued message mysteriously disappears
template <class TDataPump, class TObservableCollection>
void evaluate_emit_observe(TDataPump& datapump,
                           moducom::coap::ObservableRegistrar<TObservableCollection>& observable_registrar,
                           std::chrono::milliseconds total_since_start)
{
    using namespace moducom::coap;
    typedef typename TDataPump::netbuf_t netbuf_t;
    typedef typename TDataPump::addr_t addr_t;
    typedef moducom::pipeline::MemoryChunk::readonly_t ro_chunk_t;
    typedef typename TObservableCollection::iterator iterator;

    static std::chrono::milliseconds last(0);

    std::chrono::milliseconds elapsed = total_since_start - last;

    if(elapsed.count() > 1000)
    {
        last = total_since_start;

        iterator it = observable_registrar.begin();

        while(it != observable_registrar.end())
        {
            //std::clog << "Sending to " << addr << std::endl;
            std::clog << "Event fired" << std::endl;

#ifdef FEATURE_MCCOAP_DATAPUMP_INLINE
            NetBufEncoder<netbuf_t> encoder;
#else
            NetBufEncoder<netbuf_t&> encoder(* new netbuf_t);
#endif

            static int mid = 0;

            // we want a NON or CON since observer messages are not a normal response
            // but instead classified as 'notifications'
            Header header(Header::NonConfirmable, Header::Code::Content);

            addr_t addr = (*it).addr;
            const layer2::Token& token = (*it).token;
            // NOTE: it appears coap-cli doesn't like a sequence # of 0
            int sequence = ++(*it).sequence;
            ++it;

            header.message_id(mid++);
            header.token_length(token.length());

            encoder.header(header);
            encoder.token(token);

            encoder.option(Option::Observe, sequence); // using mid also for observe counter since we aren't doing CON it won't matter

            emit_observe(encoder, sequence);

            encoder.complete();

#ifdef FEATURE_MCCOAP_DATAPUMP_INLINE
            datapump.enqueue_out(std::forward<netbuf_t>(encoder.netbuf()), addr);
#else
            datapump.enqueue_out(encoder.netbuf(), addr);
{'fraction_non_alphanumeric': 0.11357850070721358, 'fraction_numerical': 0.0029702970297029703, 'mean_word_length': 2.8555070883315157, 'pattern_counts': {'":': 0, '<': 58, '<?xml version=': 0, '>': 40, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6529556', 'n_tokens_mistral': 2171, 'n_tokens_neox': 2060, 'n_words': 502}