{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "1+1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [],
   "source": [
    "proto_string = \"\"\"\n",
    "syntax = \"proto3\";\n",
    "package helloworld;\n",
    "\n",
    "service Greeter {\n",
    "    rpc SayHello (HelloRequest) returns (HelloReply);\n",
    "    rpc SendVoice(stream VoiceRequest) returns (Empty);\n",
    "    rpc GetVoice(Empty) returns (stream VoiceReply);\n",
    "    rpc GetCurrentUsersUUID(Empty) returns (CurrentUsersUUIDReply);\n",
    "    rpc StartSpeaking(StartSpeakingRequest) returns (Empty);\n",
    "    rpc StopSpeaking(StopSpeakingRequest) returns (Empty);\n",
    "}\n",
    "\n",
    "message Empty {\n",
    "}\n",
    "\n",
    "message VoiceRequest {\n",
    "    string uuid = 1;\n",
    "    int64 timestamp = 2;\n",
    "    bytes voice = 3;\n",
    "}\n",
    "\n",
    "message VoiceReply {\n",
    "    string uuid = 1;\n",
    "    int64 timestamp = 2;\n",
    "    bytes voice = 3;\n",
    "}\n",
    "\n",
    "message CurrentUsersUUIDReply {\n",
    "    repeated string uuid = 1;\n",
    "}\n",
    "\n",
    "message StartSpeakingRequest {\n",
    "    string uuid = 1;\n",
    "}\n",
    "\n",
    "message StopSpeakingRequest {\n",
    "    string uuid = 1;\n",
    "}\n",
    "\n",
    "message HelloRequest {\n",
    "   string name = 1;\n",
    "}\n",
    "\n",
    "message HelloReply {\n",
    "    string message = 1;\n",
    "}\n",
    "\"\"\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [],
   "source": [
    "import re"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[[' Empty', ' '],\n",
       " [' VoiceRequest',\n",
       "  ' string uuid = 1;\\n    int64 timestamp = 2;\\n    bytes voice = 3;'],\n",
       " [' VoiceReply',\n",
       "  ' string uuid = 1;\\n    int64 timestamp = 2;\\n    bytes voice = 3;'],\n",
       " [' CurrentUsersUUIDReply', ' repeated string uuid = 1;'],\n",
       " [' StartSpeakingRequest', ' string uuid = 1;'],\n",
       " [' StopSpeakingRequest', ' string uuid = 1;'],\n",
       " [' HelloRequest', ' string name = 1;'],\n",
       " [' HelloReply', ' string message = 1;']]"
      ]
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "found = re.findall(r\"message\\s+(?P<object_name>\\w+)\\s+\\{(?P<properties>(\\s*.*?\\s*)+)\\}\", proto_string, re.DOTALL)\n",
    "found = [\n",
    "            [\" \" + string.strip() for string in one][:2]\n",
    "            for one in found\n",
    "        ]\n",
    "found"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['Empty', []]\n",
      "['VoiceRequest', [('', 'string', 'uuid'), ('', 'int64', 'timestamp'), ('', 'bytes', 'voice')]]\n",
      "['VoiceReply', [('', 'string', 'uuid'), ('', 'int64', 'timestamp'), ('', 'bytes', 'voice')]]\n",
      "['CurrentUsersUUIDReply', [('repeated', 'string', 'uuid')]]\n",
      "['StartSpeakingRequest', [('', 'string', 'uuid')]]\n",
      "['StopSpeakingRequest', [('', 'string', 'uuid')]]\n",
      "['HelloRequest', [('', 'string', 'name')]]\n",
      "['HelloReply', [('', 'string', 'message')]]\n"
     ]
    }
   ],
   "source": [
    "found_2 = []\n",
    "for one in found.copy():\n",
    "    if len(one) == 2:\n",
    "        class_name = one[0]\n",
    "        property_text = one[1]\n",
    "        if len(property_text) == 0:\n",
    "            continue\n",
    "        #property_list = re.findall(r\"\\w+\\s+(?P<property>\\w+)\\s+=\\s+\\d+;\", property_text)\n",
    "        # print(class_name, property_list)\n",
    "        property_list = re.findall(r\"(?P<feature>\\w*)\\s+(?P<type>\\w+)\\s+(?P<property>\\w+)\\s+=\\s+\\d+;\", property_text)\n",
    "        found_2.append([class_name.strip(), property_list])\n",
    "        print(found_2[-1])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{\n",
      "    \"Empty\": {},\n",
      "    \"VoiceRequest\": {\n",
      "        \"uuid\": {\n",
      "            \"type\": \"string\",\n",
      "            \"nullable\": false,\n",
      "            \"is_list\": false\n",
      "        },\n",
      "        \"timestamp\": {\n",
      "            \"type\": \"int64\",\n",
      "            \"nullable\": false,\n",
      "            \"is_list\": false\n",
      "        },\n",
      "        \"voice\": {\n",
      "            \"type\": \"bytes\",\n",
      "            \"nullable\": false,\n",
      "            \"is_list\": false\n",
      "        }\n",
      "    },\n",
      "    \"VoiceReply\": {\n",
      "        \"uuid\": {\n",
      "            \"type\": \"string\",\n",
      "            \"nullable\": false,\n",
      "            \"is_list\": false\n",
      "        },\n",
      "        \"timestamp\": {\n",
      "            \"type\": \"int64\",\n",
      "            \"nullable\": false,\n",
      "            \"is_list\": false\n",
      "        },\n",
      "        \"voice\": {\n",
      "            \"type\": \"bytes\",\n",
      "            \"nullable\": false,\n",
      "            \"is_list\": false\n",
      "        }\n",
      "    },\n",
      "    \"CurrentUsersUUIDReply\": {\n",
      "        \"uuid\": {\n",
      "            \"type\": \"string\",\n",
      "            \"nullable\": false,\n",
      "            \"is_list\": true\n",
      "        }\n",
      "    },\n",
      "    \"StartSpeakingRequest\": {\n",
      "        \"uuid\": {\n",
      "            \"type\": \"string\",\n",
      "            \"nullable\": false,\n",
      "            \"is_list\": false\n",
      "        }\n",
      "    },\n",
      "    \"StopSpeakingRequest\": {\n",
      "        \"uuid\": {\n",
      "            \"type\": \"string\",\n",
      "            \"nullable\": false,\n",
      "            \"is_list\": false\n",
      "        }\n",
      "    },\n",
      "    \"HelloRequest\": {\n",
      "        \"name\": {\n",
      "            \"type\": \"string\",\n",
      "            \"nullable\": false,\n",
      "            \"is_list\": false\n",
      "        }\n",
      "    },\n",
      "    \"HelloReply\": {\n",
      "        \"message\": {\n",
      "            \"type\": \"string\",\n",
      "            \"nullable\": false,\n",
      "            \"is_list\": false\n",
      "        }\n",
      "    }\n",
      "}\n"
     ]
    }
   ],
   "source": [
    "import json\n",
    "\n",
    "defination_tree = {}\n",
    "for one in found_2.copy():\n",
    "    class_name = one[0]\n",
    "    variable_list = one[1]\n",
    "\n",
    "    defination_tree[class_name] = {}\n",
    "    for one_variable in variable_list:\n",
    "        feature = one_variable[0]\n",
    "        type = one_variable[1]\n",
    "        name = one_variable[2]\n",
    "        defination_tree[class_name][name] = {\n",
    "            \"type\": type, \n",
    "            \"nullable\": True if feature == \"optional\" else False,\n",
    "            \"is_list\": True if feature == \"repeated\" else False\n",
    "        }\n",
    "\n",
    "print(json.dumps(defination_tree, indent=4, sort_keys=False))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "{\n",
      "    \"Okok\": {\n",
      "        \"Option\": [\n",
      "            null, \n",
      "            null\n",
      "        ]\n",
      "    }, \n",
      "    \"Page_size\": \"2\", \n",
      "    \"Page_number\": {\n",
      "        \"ok\": \"xx\",\n",
      "        \"no\": \"xx\"\n",
      "    }\n",
      "}\n",
      "\n"
     ]
    }
   ],
   "source": [
    "import re\n",
    "from typing import Any\n",
    "\n",
    "Null_value_identify_symbol = \"xx\"\n",
    "\n",
    "def replace_null_to_null_identify_symbol(json_string: str) -> str:\n",
    "    def try_to_do_a_replace(match_obj: Any):\n",
    "        if match_obj.group() is not None:\n",
    "            before = match_obj.group('before')\n",
    "            null = match_obj.group('null')\n",
    "            after = match_obj.group('after')\n",
    "            return f'{before}\"{Null_value_identify_symbol}\"{after}'\n",
    "    result = re.sub(r\"(?P<before>\\\"\\w+?\\\"\\s*:\\s*)(?P<null>null)(?P<after>,?)\", try_to_do_a_replace, json_string, flags=re.MULTILINE) #type: ignore\n",
    "    return result #type: ignore\n",
    "\n",
    "result = replace_null_to_null_identify_symbol(\"\"\"\n",
    "{\n",
    "    \"Okok\": {\n",
    "        \"Option\": [\n",
    "            null, \n",
    "            null\n",
    "        ]\n",
    "    }, \n",
    "    \"Page_size\": \"2\", \n",
    "    \"Page_number\": {\n",
    "        \"ok\": null,\n",
    "        \"no\": null\n",
    "    }\n",
    "}\n",
    "\"\"\")\n",
    "print(result)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3.10.8 64-bit",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.9"
  },
  "orig_nbformat": 4,
  "vscode": {
   "interpreter": {
    "hash": "b0fa6594d8f4cbf19f97940f81e996739fb7646882a419484c72d19e05852a7e"
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
